﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using TestVisioCanvas.Models;
using System.Windows;

namespace TestVisioCanvas.ViewModel
{
    /// <summary>
    /// ViewModel for the MainWindow
    /// </summary>
    class MainWindowViewModel : Models.BaseNotify
    {
        // Collection of the invoices
#warning forse inutile
        private ObservableCollection<Models.InvoiceModel> _invoices =
            new ObservableCollection<Models.InvoiceModel>();

        // Collection of the Visio Standard Shapes
        private ObservableCollection<MasterModel> _masters =
            new ObservableCollection<MasterModel>();

        // Collection of the selected products
        private ObservableCollection<Models.ProductModel> _products =
            new ObservableCollection<Models.ProductModel>();

        // Internal Selection (used for visualization purposes)
        private IEnumerable<Models.MasterModel> _MastersQuery;
        private IEnumerable<Models.ProductModel> _ProductQuery;

        // Products Grid layout
        private int _rows = 4, _columns = 2;
        private int _currentPage = 0;
        public int ProductsPerPage { get { return Rows * Columns; } }

        //Height,Widths and margins in order to obtain the exact layout desider by Dr. Passamonti        
        #region LAYOUT  
        private double Vratio;
        private double Hratio;
        private double _DuplicateBTW = 40;
        private double _FlipHorBT_np_scroll = 47;
        private double _FlipVertBT = 43;
        private double _AlignHorBT = 54;
        private double _AlignVertBT = 31;
        private double _circularBT = 52;
        private double _rect_BT = 80;
        
        public double DuplicateBTWidth
        {
            get { return _DuplicateBTW; }
            set
            {
                _DuplicateBTW = value;
                OnPropertyChanged("DuplicateBTWidth");
            }
        }

        //flip horizontal and new page buttons
        public double Rect_BT
        {
            get { return _rect_BT; }
            set
            {
                _rect_BT = value;
                OnPropertyChanged("Rect_BT");
            }
        }

        public double CircularBT
        {
            get { return _circularBT; }
            set
            {
                _circularBT = value;
                OnPropertyChanged("CircularBT");
            }
        }
        
        public double AlignVertBT
        {
            get { return _AlignVertBT; }
            set
            {
                _AlignVertBT = value;
                OnPropertyChanged("AlignVertBT");
            }
        }
        public double AlignHorBT
        {
            get { return _AlignHorBT; }
            set
            {
                _AlignHorBT = value;
                OnPropertyChanged("AlignHorBT");
            }
        }
        public double FlipVertBT
        {
            get { return _FlipVertBT; }
            set
            {
                _FlipVertBT = value;
                OnPropertyChanged("FlipVertBT");
            }
        }
        public double FlipHorBT_np_scroll
        {
            get { return _FlipHorBT_np_scroll; }
            set
            {
                _FlipHorBT_np_scroll = value;
                OnPropertyChanged("FlipHorBT_np_scroll");
            }
        }

        private Thickness _ProductMargin = new Thickness(10, 14, 10, 14);
        
        public Thickness ProductMargin
        {
            get { return _ProductMargin; }
            set 
            { 
                _ProductMargin = value;
                OnPropertyChanged("ProductMargin");
                OnPropertyChanged("NegProductMargin");
            }
        }

        public Thickness NegProductMargin
        {
            get { return new Thickness(
                -ProductMargin.Left, -ProductMargin.Top,
                -ProductMargin.Right, -ProductMargin.Bottom); }
        }
        
        #endregion

        public MainWindowViewModel()
        {
            CurrentPage = 0;        
            Vratio = (System.Windows.SystemParameters.PrimaryScreenHeight / 900);
            Hratio = (System.Windows.SystemParameters.PrimaryScreenWidth / 1440);            
            AdaptLayout();                     
        }

        private void AdaptLayout()
        {
            DuplicateBTWidth *= Hratio;
            FlipHorBT_np_scroll *= Hratio;
            FlipVertBT *= Hratio;
            AlignHorBT *= Hratio;
            AlignVertBT *= Hratio;
            CircularBT *= Hratio;
            Rect_BT *= Hratio;
            ProductMargin = new Thickness(
                ProductMargin.Left * Hratio, ProductMargin.Top * Vratio,
                ProductMargin.Right * Hratio, ProductMargin.Bottom * Vratio);
        }

        public void RemoveProduct(ProductModel item)
        {
            _products.Remove(item);
            CurrentPage = Math.Min(_currentPage, LastPage);
        }

        public int LastPage
        {
            get { return 
                Math.Max(0,
                (int)Math.Ceiling((float)Products.Count / ProductsPerPage - 1)); }
        }

        public int CurrentPage
        {
            get { return _currentPage; }
            set
            {
                _currentPage = Math.Min(LastPage, Math.Max(0, value));
                ProductQuery = Products.Skip(CurrentPage * ProductsPerPage).Take(ProductsPerPage);
                OnPropertyChanged("CurrentPage");
            }
        }

        public int Columns
        {
            get { return _columns; }
            set
            {
                _columns = value;
                OnPropertyChanged("Columns");
            }
        }

        public int Rows
        {
            get { return _rows; }
            set
            {
                _rows = value;
                OnPropertyChanged("Rows");
            }
        }

        /// <summary>
        /// Exposes the ProductQuery
        /// </summary>
        public IEnumerable<Models.ProductModel> ProductQuery
        {
            get { return _ProductQuery; }
            private set
            {
                _ProductQuery = value;
                OnPropertyChanged("ProductQuery");
            }
        }

        public IEnumerable<Models.MasterModel> MastersQuery
        {
            get { return _MastersQuery; }
            private set
            {
                _MastersQuery = value;
                OnPropertyChanged("MastersQuery");
            }
        }

        public void ChangeCategory(Models.MasterCategory Category)
        {
            MastersQuery = _masters.Where(x => x.Category == Category);
        }

        public ObservableCollection<Models.ProductModel> Products
        {
            get { return _products; }
            set
            {
                _products = value;
                OnPropertyChanged("Products");
            }
        }

        public ObservableCollection<MasterModel> Masters
        {
            get { return _masters; }
            set
            {
                _masters = value;
                OnPropertyChanged("Masters");
            }
        }        

        #region INVOICES MANAGEMENT
        /// <summary>
        /// Collection of the invoices
        /// </summary>
        public ObservableCollection<Models.InvoiceModel> SelectedProducts
        {
            get { return _invoices; }
        }



        /// <summary>
        /// Total cost of the invoice
        /// </summary>
        public double TotalCost
        {
            get { return _invoices.Sum(x => x.TotalCost); }
        }

        /// <summary>
        /// Method that adds a product on the invoice.
        /// </summary>
        /// <param name="item">The product to add</param>
        public void Add(Wrappers.SellableShape item)
        {
#warning confronto che dovrà essere fatto in base al codice interno
            // tries to find the product inside the invoice.
            var p =
                _invoices.FirstOrDefault(x => x.Product.ProductDetails.PSMNTProductCode == item.ProductDetails.PSMNTProductCode);
            // if the product is already present on the invoice it updates the quantity
            if (p != null)
            {
                p.Quantity++;
            }
            // if not, the product "record" is added to the invoice
            else
            {
                _invoices.Add(new Models.InvoiceModel(item));
            }
            OnPropertyChanged("TotalCost");
        }

        /// <summary>
        /// Method that removes a product from the invoice
        /// </summary>
        /// <param name="item">The product to remove</param>
        public void Remove(Wrappers.SellableShape item)
        {
            // tries to find the product inside the invoice.
            var p =
                _invoices.FirstOrDefault(x => x.Product.ProductDetails.PSMNTProductCode == item.ProductDetails.PSMNTProductCode);
            // if the product is present
            if (p != null)
            {
                // updates its quantity
                p.Quantity--;
                // if quantity equals 0, the product "record" is removed from the invoice
                if (p.Quantity == 0)
                {
                    _invoices.Remove(p);
                }
            }
            OnPropertyChanged("TotalCost");
        }
        #endregion
    }
}